﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Runtime.Serialization;

namespace ITSP.SharePoint.CacheRefresh.Utilities
{
    /// <summary>
    /// Advanced Serialisation Utilities.
    /// These use the DataContractSerializer.
    /// </summary>
    public static class DataSerialisationUtils
    {
        /// <summary>
        /// Serialize the Type using the Data Contract Serializer.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string Serialize<T>(T value)
        {

            if (value == null)
            {
                return null;
            }

            // use reflection to get all derived types
            List<Type> knownTypes = new List<Type>();
            Type serializableType = typeof(T);
            foreach (Type t in serializableType.Assembly.GetTypes())
            {
                if (serializableType.IsAssignableFrom(t))
                {
                    knownTypes.Add(t);
                }
            }

            return Serialize<T>(value, knownTypes);
        }

        /// <summary>
        /// Serialize the Type using the Data Contract Serializer.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <param name="includeTypes"></param>
        /// <returns></returns>
        public static string Serialize<T>(T value, IList<Type> includeTypes)
        {

            if (value == null)
            {
                return null;
            }

            DataContractSerializer serializer = new DataContractSerializer(typeof(T), includeTypes.ToArray());

            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Encoding = new UnicodeEncoding(false, false); // no BOM in a .NET string
            settings.Indent = false;
            settings.OmitXmlDeclaration = false;

            using (StringWriter textWriter = new StringWriter())
            {
                using (XmlWriter xmlWriter = XmlWriter.Create(textWriter, settings))
                {
                    serializer.WriteObject(xmlWriter, value);
                }
                return textWriter.ToString();
            }
        }

        /// <summary>
        /// Deserialize the Type using the Data Contract Serializer.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="xml"></param>
        /// <returns></returns>
        public static T Deserialize<T>(string xml)
        {

            if (string.IsNullOrEmpty(xml))
            {
                return default(T);
            }

            DataContractSerializer serializer = new DataContractSerializer(typeof(T));

            XmlReaderSettings settings = new XmlReaderSettings();
            // No settings need modifying here

            using (StringReader textReader = new StringReader(xml))
            {
                using (XmlReader xmlReader = XmlReader.Create(textReader, settings))
                {
                    return (T)serializer.ReadObject(xmlReader);
                }
            }
        }
    }
}
